package com.nuoniu.sibanyun.service.erp.barcode.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.entity.dto.ErpBarcodeInOutSaveDto;
import com.nuoniu.sibanyun.entity.erp.barcode.ErpBarcodeInOut;
import com.nuoniu.sibanyun.entity.erp.barcode.ErpNsInOutDetail;
import com.nuoniu.sibanyun.entity.erp.barcode.vo.BarcodeInOutStatisticVo;
import com.nuoniu.sibanyun.mapper.erp.barcode.ErpBarcodeInOutMapper;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.barcode.IErpBarcodeInOutService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import lombok.Data;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 条码出入库 服务实现类
 * </p>
 *
 * @author 白强
 * @since 2021-11-30
 */
@Service
public class ErpBarcodeInOutServiceImpl extends ServiceImpl<ErpBarcodeInOutMapper, ErpBarcodeInOut> implements IErpBarcodeInOutService {

    @Autowired
    private IErpAccountService erpAccountService;

    @Override
    public void saveErpBarcodeInOut(ErpBarcodeInOutSaveDto erpBarcodeInOutSaveDto) {
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        UserInfo userInfo = UserThreadLocal.get();
        LocalDateTime now = LocalDateTime.now();
        Integer type = erpBarcodeInOutSaveDto.getType();
        if(type != 1 && type != 2) {
            throw new NuoNiuException("参数错误");
        }
        String barcode = erpBarcodeInOutSaveDto.getBarcode();
        ErpBarcodeInOut newErpBarcodeInOut = getByBarcode(barcode);
        if(null != newErpBarcodeInOut){
            if(1 == type) {
                throw new NuoNiuException("条码对应的商品已经入库");
            }
            LocalDateTime outTime = newErpBarcodeInOut.getOutTime();
            if(null != outTime) {
                throw new NuoNiuException("条码对应的商品已经出库");
            }
            newErpBarcodeInOut.setOutTime(now);
            newErpBarcodeInOut.setOutUserId(userInfo.getUserId());
            newErpBarcodeInOut.setOutUserName(userInfo.getRealName());
        }else{
            if(2 == type) {
                throw new NuoNiuException("参数错误");
            }
            newErpBarcodeInOut = new ErpBarcodeInOut();
            newErpBarcodeInOut.setCompanyId(userInfo.getCompanyId());
            newErpBarcodeInOut.setAccountId(currentAccountId);
            newErpBarcodeInOut.setSourceDetailId(erpBarcodeInOutSaveDto.getSourceDetailId());
            newErpBarcodeInOut.setSourceVoucherId(erpBarcodeInOutSaveDto.getSourceVoucherId());
            newErpBarcodeInOut.setSourceVoucherType(erpBarcodeInOutSaveDto.getSourceVoucherType());
            newErpBarcodeInOut.setWarehouseId(erpBarcodeInOutSaveDto.getWarehouseId());
            newErpBarcodeInOut.setWarehouseName(erpBarcodeInOutSaveDto.getWarehouseName());
            newErpBarcodeInOut.setWarehouseCode(erpBarcodeInOutSaveDto.getWarehouseCode());
            newErpBarcodeInOut.setBarcode(barcode);
            newErpBarcodeInOut.setInTime(now);
            newErpBarcodeInOut.setInUserId(userInfo.getUserId());
            newErpBarcodeInOut.setInUserName(userInfo.getRealName());
        }
        saveOrUpdate(newErpBarcodeInOut);
    }

    @Override
    public ErpBarcodeInOut getByBarcode(String barcode) {
        if(StringUtils.isBlank(barcode)) {
            throw new NuoNiuException("条码不能为空！");
        }
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<ErpBarcodeInOut> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.eq("barcode",barcode);
        queryWrapper.eq("is_last",1);
        queryWrapper.last("LIMIT 1");
        ErpBarcodeInOut barcodeInOut = getOne(queryWrapper);
        return barcodeInOut;
    }

    @Override
    public void bathUpdateOutRecord(List<ErpNsInOutDetail> erpNsInOutDetailList) {
        LocalDateTime now = LocalDateTime.now();
        UserInfo userInfo = UserThreadLocal.get();
        List<String> barcodeList = erpNsInOutDetailList.stream().map(ErpNsInOutDetail::getBarcodes).collect(Collectors.toList());
        String joinBarcodes = StringUtils.join(barcodeList, ",");
        List<String> barcodeStrList = Arrays.asList(joinBarcodes.split(","));
        if(barcodeStrList.size() == 0) {
            throw new NuoNiuException("审核失败，参数错误");
        }
        /** 校验 条码出入库 状态 */
        checkRecord(2,barcodeStrList);
        //更新 出库时间
        UpdateWrapper<ErpBarcodeInOut> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("barcode",barcodeStrList);
        updateWrapper.eq("company_id",userInfo.getCompanyId());
        updateWrapper.set("out_time",now);
        updateWrapper.set("out_user_id",userInfo.getUserId());
        updateWrapper.set("out_user_name",userInfo.getRealName());
        update(updateWrapper);

    }

    @Override
    public void bathUpdateOutRecordFromBarcodes(List<String> barcodes) {
        LocalDateTime now = LocalDateTime.now();
        UserInfo userInfo = UserThreadLocal.get();
        if(barcodes.size() == 0) {
            throw new NuoNiuException("审核失败，参数错误");
        }
        /** 校验 条码出入库 状态 */
        checkRecord(2,barcodes);
        //更新 出库时间
        UpdateWrapper<ErpBarcodeInOut> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("barcode",barcodes);
        updateWrapper.eq("company_id",userInfo.getCompanyId());
        updateWrapper.set("out_time",now);
        updateWrapper.set("out_user_id",userInfo.getUserId());
        updateWrapper.set("out_user_name",userInfo.getRealName());
        update(updateWrapper);
    }
    /**
     * 校验 条码 出入库 状态
     * @param businessType  1: 入库业务 校验 2: 出库业务校验
     * @param barcodeList
     */
    @Override
    public void checkRecord(Integer businessType, List<String> barcodeList) {
       List<String> warnMessageList = new ArrayList<>();
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<ErpBarcodeInOut> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.in("barcode",barcodeList);
        queryWrapper.eq("is_last",1);
        List<ErpBarcodeInOut> erpBarcodeInOutList = list(queryWrapper);
        /** 找到 的 条码 */
        List<String> findBarCodes = erpBarcodeInOutList.stream().map(ErpBarcodeInOut::getBarcode).collect(Collectors.toList());
        /** 入库业务 */
        if( 1 == businessType){
            if(findBarCodes.size() > 0){
                String barcode = StringUtils.join(findBarCodes, ",");
                warnMessageList.add("条码：" + barcode +"：已经入库！");
            }
        }
        /** 出库业务 */
        else if(2 == businessType){
            /**  没有找到的条码 ： 删除 找到的 记录 条码*/
            List<String> noFindInBarCodeList = new ArrayList<>(barcodeList);
            noFindInBarCodeList.removeAll(findBarCodes);
            if(noFindInBarCodeList.size() > 0){
                String barcode = StringUtils.join(noFindInBarCodeList, ",");
                warnMessageList.add("条码：" + barcode +"：还未入库！");
            }
            /** 校验是否 已经出库*/
            List<String> outBarCodes = erpBarcodeInOutList.stream().filter(item -> null != item.getOutTime()).map(ErpBarcodeInOut::getBarcode).collect(Collectors.toList());
            if(outBarCodes.size() > 0){
                String barcode = StringUtils.join(outBarCodes, ",");
                warnMessageList.add("条码：" + barcode +"：已经出库！");
            }
        }
        if(warnMessageList.size() > 0){
            String warnMessage = StringUtils.join(warnMessageList,"；");
            throw new NuoNiuException(warnMessage);
        }
    }


    @Override
    public List<BarcodeInOutStatisticVo> getInOutRecord(String sourceVoucherType, Integer sourceVoucherId) {
        UserInfo userInfo = UserThreadLocal.get();
        return baseMapper.getInOutRecord(userInfo.getCompanyId(),sourceVoucherType,sourceVoucherId);
    }


    @Override
    public BarcodeInOutStatisticVo getBatchInOutRecord(Integer companyId, String sourceVoucherType, Integer sourceVoucherId) {
        UserInfo userInfo = UserThreadLocal.get();
        return baseMapper.getBatchInOutRecord(userInfo.getCompanyId(),sourceVoucherType,sourceVoucherId);
    }

}
